package com.atguigu.gmall.cart.service;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.feign.GmallPmsClient;
import com.atguigu.gmall.cart.feign.GmallSmsClient;
import com.atguigu.gmall.cart.feign.GmallWmsClient;
import com.atguigu.gmall.cart.intercepter.LoginIntercepter;
import com.atguigu.gmall.cart.mapper.CartMapper;
import com.atguigu.gmall.cart.pojo.Cart;
import com.atguigu.gmall.cart.pojo.UserInfo;
import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.common.exception.CartException;
import com.atguigu.gmall.pms.api.GmallPmsApi;
import com.atguigu.gmall.pms.entity.SkuAttrValueEntity;
import com.atguigu.gmall.pms.entity.SkuEntity;
import com.atguigu.gmall.sms.api.GmallSmsApi;
import com.atguigu.gmall.sms.vo.ItemSaleVo;
import com.atguigu.gmall.wms.api.GmallWmsApi;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import net.sf.jsqlparser.util.deparser.UpdateDeParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.security.KeyPairGenerator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CartService {
    @Autowired
    GmallPmsClient gmallPmsClient;

    @Autowired
    GmallSmsClient gmallSmsClient;
    @Autowired
    GmallWmsClient gmallWmsClient;
    @Autowired
    StringRedisTemplate redisTemplate;
    private static final String PRICE_PREFIX = "cart:price:";
    private final static String KEY_PREFIX = "cart:info:";

    @Autowired
    CartAsyncService cartAsyncService;
    /**
     * 添加商品到购物车
     * @param cart
     */
    public void addCart(Cart cart) {
        //获取用户的基本信息
        String userId = this.getUserId();
        String skuId = cart.getSkuId().toString();
        //2、判断购物车中是否有该商品，如果有则对数量进行加1，
        BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(KEY_PREFIX + userId);
        if (hashOps.hasKey(skuId)){
            //包含则更新数量
            //1、更新redis
            String skuJson = hashOps.get(skuId).toString();
            BigDecimal count = cart.getCount();//添加到购物车的数量
            cart = JSON.parseObject(skuJson, Cart.class);//查询出已有的数量
            cart.setCount(cart.getCount().add(count));//二者相加
            //2、更新mysql数据库中的数据
            cartAsyncService.update(userId,cart,skuId);
        }else {
        // 如果没有则对购物车的表redis+mysql进行添加记录的操作
             //2、根据skuId，查询sku相关的所有信息，并将其设置到cart中
        ResponseVo<SkuEntity> skuEntityResponseVo = gmallPmsClient.querySkuById(cart.getSkuId());
        SkuEntity skuEntity = skuEntityResponseVo.getData();
        if (skuEntity==null){
            throw new CartException("您新增的商品不存在");
        }
        cart.setDefaultImage(skuEntity.getDefaultImage());
        cart.setPrice(skuEntity.getPrice());
        cart.setTitle(skuEntity.getTitle());
        cart.setUserId(userId);
        //查询营销信息
            ResponseVo<List<ItemSaleVo>> itemSaleInfoBySkuId = gmallSmsClient.getItemSaleInfoBySkuId(cart.getSkuId());
            List<ItemSaleVo> itemSaleVos = itemSaleInfoBySkuId.getData();
           cart.setSales(JSON.toJSONString(itemSaleVos));
        //查询是否选中
            cart.setCheck(true);
        //设置是否有货
            ResponseVo<List<WareSkuEntity>> listResponseVo = gmallWmsClient.queryWareSkuBySkuId(cart.getSkuId());
            List<WareSkuEntity> wareSkuEntities = listResponseVo.getData();
            if (!CollectionUtils.isEmpty(wareSkuEntities)){
               cart.setStore(wareSkuEntities.stream().anyMatch(waresku->waresku.getStock()>waresku.getStockLocked()));
            }
            //设置销售属性
            ResponseVo<List<SkuAttrValueEntity>> salesAttrResponseVo = this.gmallPmsClient.querySaleAttrValuesBySkuId(cart.getSkuId());
            List<SkuAttrValueEntity> attrValueEntityList = salesAttrResponseVo.getData();
            if (!CollectionUtils.isEmpty(attrValueEntityList)){
                cart.setSaleAttrs(JSON.toJSONString(attrValueEntityList));
            }
        //添加到mysql数据库

            this.cartAsyncService.insert(userId,cart);
        }
        this.redisTemplate.opsForValue().set(PRICE_PREFIX+skuId,cart.getPrice().toString());
        hashOps.put(skuId,JSON.toJSONString(cart));
    }

    /**
     * 获取用户的id
     * @return
     */
    private String getUserId(){
        UserInfo userInfo = LoginIntercepter.getUserInfo();
        String userId ;
        //1、如果用户的id为null说明未登录，使用userKey作为键，将用户的添加的购物车信息添加到redis缓存中
        if (userInfo.getUserId()==null){
            userId=userInfo.getUserKey();
        }else {
        userId = userInfo.getUserId().toString();
        }
        return userId;
    }

    /**
     * 通过skuId查询购物车
     * @param skuId
     * @return
     */
    public Cart queryCartBySkuId(Long skuId) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        String json = hashOps.get(skuId.toString()).toString();
        Cart cart = JSON.parseObject(json, Cart.class);
        String price = this.redisTemplate.opsForValue().get(PRICE_PREFIX + skuId);
        cart.setPrice(new BigDecimal(price));
        return cart;
    }

    /**
     * 查询购物车列表信息
     * @return
     */
    public List<Cart> queryCarts() {

        UserInfo userInfo = LoginIntercepter.getUserInfo();
        String userKey = userInfo.getUserKey();
        Long userId = userInfo.getUserId();
        //通过userkey查询未登录用户的购物车信息
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX+userKey);
        List<Object> unloginCartjson = hashOps.values();
        List<Cart> unloginCart = null;
            //提取userKey中的购物车信息
            if (!CollectionUtils.isEmpty(unloginCartjson)){
                unloginCart = unloginCartjson.stream().map(cart ->
                        {
                            Cart cart1 = JSON.parseObject(cart.toString(), Cart.class);
                            String price = this.redisTemplate.opsForValue().get(PRICE_PREFIX + cart1.getSkuId());
                            cart1.setCurrentPrice(new BigDecimal(price));
                            return  cart1;
                        }
                        ).collect(Collectors.toList());
            }
        //判断用户是否登录
            if (userId==null){
                return unloginCart;
            }
        //反之用户已登录
        BoundHashOperations<String, Object, Object> loginHashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);

        if (!CollectionUtils.isEmpty(unloginCart)){
        //TODO 合并购物车
        unloginCart.forEach(cart -> {
                    Long skuId = cart.getSkuId();
                    if (!loginHashOps.hasKey(skuId.toString())) {
                        //说明没有此项购物车记录，直接添加记录到loginCart中,直接新增一条记录
                        cart.setId(null);
                        cart.setUserId(userId.toString());
                        this.cartAsyncService.insert(userId.toString(),cart);
                    } else {
                        //说明有此项购物车记录，向数据库中的数量进行加操作
                        String cartjson = loginHashOps.get(cart.getSkuId().toString()).toString();
                        BigDecimal count = cart.getCount();
                        cart = JSON.parseObject(cartjson, Cart.class);
                        cart.setCount(cart.getCount().add(count));
                        this.cartAsyncService.update(userId.toString(),cart,skuId.toString());
                    }

                    loginHashOps.put(skuId.toString(), JSON.toJSONString(cart));
                });
        //清空未登录购物车
            this.redisTemplate.delete(KEY_PREFIX+userKey);
            this.cartAsyncService.delete(userKey);

            //再次查询登录购物车，并返回
        }
        List<Object> loginCartJsons = loginHashOps.values();
        if (!CollectionUtils.isEmpty(loginCartJsons)){
            return loginCartJsons.stream().map(cartJson -> {
                Cart cart = JSON.parseObject(cartJson.toString(), Cart.class);
                String price = this.redisTemplate.opsForValue().get(PRICE_PREFIX + cart.getSkuId());
                cart.setCurrentPrice(new BigDecimal(price));
                return cart;
            }).collect(Collectors.toList());
        }
        return null;
    }

    /**
     * 删除购物车中指定skuId的sku
     * @param skuId
     */
    public void deleteBySkuId(Long skuId) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        if (hashOps.hasKey(skuId.toString())){
            hashOps.delete(skuId.toString());
            this.cartAsyncService.deleteBySkuId(userId,skuId);
        }
    }


    /**
     * 更新购物车中指定的数sku的数量
     * @param cart
     */
    public void updateNum(Cart cart) {
        if (cart!=null){
            String userId = this.getUserId();
            BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
            if (!hashOps.hasKey(cart.getSkuId().toString())) {
                throw new CartException("您要更新的购物车不存在");
            }
            //获取更新的数量
            BigDecimal count = cart.getCount();
            String cartJson = hashOps.get(cart.getSkuId().toString()).toString();
            cart = JSON.parseObject(cartJson, Cart.class);
            cart.setCount(count);
            hashOps.put(cart.getSkuId().toString(),JSON.toJSONString(cart));
            this.cartAsyncService.update(userId,cart,cart.getSkuId().toString());
        }
    }

    //根据用户的id查询对应的购物车列表
    public List<Cart> getCartInfoByUserId(Long userId) {
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        List<Object> orderJson = hashOps.values();
        if (CollectionUtils.isEmpty(orderJson)){
            return null;
        }
        return orderJson.stream().map(t -> {
            Cart cart = JSON.parseObject(t.toString(), Cart.class);
            return cart;
        }).filter(Cart::getCheck).collect(Collectors.toList());
    }

    //更改对应skuId的选中状态
    public void updateStatus(Cart cart) {
        String userId = this.getUserId();
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(KEY_PREFIX + userId);
        Object o = hashOps.get(cart.getSkuId().toString());
        if (o!=null){
            Boolean check = cart.getCheck();
            cart = JSON.parseObject(o.toString(), Cart.class);
            cart.setCheck(check);
            hashOps.put(cart.getSkuId().toString(),JSON.toJSONString(cart));
        }
        //修改数据库中的选中状态
        this.cartAsyncService.update(userId,cart,cart.getSkuId().toString());

    }
}
